package org.apache.ocean;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.ocean.util.OceanConcurrentHashMap;

/**
 * 
 * @author jasonr
 */
public class HighlightCache {
	private LinkedHashMap<HighlightKey, Result> resultsMap;
	public ConcurrentHashMap<IDVersion, List<HighlightKey>> idVersionMap;
	private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

	public HighlightCache(int maxSize) {
		resultsMap = new LRUMap<HighlightKey, Result>(maxSize, maxSize);
		idVersionMap = new OceanConcurrentHashMap<IDVersion, List<HighlightKey>>();
	}

	public Result get(HighlightKey highlightKey) {
		LockUtil.lock(lock.readLock());
		try {
			return resultsMap.get(highlightKey);
		} finally {
			lock.readLock().unlock();
		}
	}

	public void add(HighlightKey highlightKey) {
		LockUtil.lock(lock.writeLock());
		try {

		} finally {
			lock.writeLock().unlock();
		}
	}

	public void remove(IDVersion idVersion) {
		if (idVersion == null)
			throw new IllegalArgumentException("idVersion null");
		LockUtil.lock(lock.writeLock());
		try {
			List<HighlightKey> list = idVersionMap.get(idVersion);
			if (list != null) {
				for (HighlightKey key : list) {
					resultsMap.remove(key);
				}
			}
			idVersionMap.remove(idVersion);
		} finally {
			lock.writeLock().unlock();
		}
	}

	public static class Result {
		public Long id;
		public Long version;
		public String snippet;

	}

	public class LRUMap<K, V> extends LinkedHashMap<K, V> {
		public int maxSize;

		public LRUMap(int size, int maxSize) {
			super(size);
			this.maxSize = maxSize;
		}

		protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
			if (size() > maxSize)
				return true;
			return false;
		}
	}

	public static class HighlightKey {
		public SortedSet<String> fields;
		public Long id;
		public Long version;
		private int hashCode;

		public HighlightKey(Long id, Long version, SortedSet<String> fields) {
			this.id = id;
			this.version = version;
			this.fields = fields;
			if (id == null)
				throw new IllegalArgumentException("id null");
			if (version == null)
				throw new IllegalArgumentException("version null");
			if (fields == null)
				throw new IllegalArgumentException("fields null");

			HashCodeBuilder builder = new HashCodeBuilder();
			builder.append(fields);
			builder.append(id);
			builder.append(version);
			hashCode = builder.toHashCode();
		}

		public boolean equals(Object object) {
			if (!(object instanceof HighlightKey))
				return false;
			if (object == null)
				return false;
			HighlightKey other = (HighlightKey) object;
			if (!ObjectUtils.equals(id, other.id))
				return false;
			if (!ObjectUtils.equals(version, other.version))
				return false;
			if (!ObjectUtils.equals(fields, other.fields))
				return false;
			return true;
		}

		public int hashCode() {
			return hashCode;
		}
	}
}
